package de.tu_darmstadt.gdi1.xcom.tests.testcases.students;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1;

/**
 * 
 * Tests if movements and rotations are performed correctly
 * 
 * @author Lukas Schwoebel
 *
 */
public class MovementTest {
	
	private XcomTestAdapterLevel1 testAdapter;
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testAdapter = new XcomTestAdapterLevel1();
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#rotateActivePlayer()}.
	 */
	@Test
	public final void testDoRotations() {
		testAdapter.loadLevelFromString(TestLevel.testLevel);

		String[] directions = {"North", "East", "South", "West"};
		
		// rotate by 720 degrees clockwise
		int i = 0;
		for(int n = 0; n < 8; n++) {
			assertEquals("The first player should face the direction "+directions[i], i+1, testAdapter.activePlayerLookingToDirection());
			testAdapter.rotateActivePlayer(true);
			i++;
			i = i % 4;
		}
		
		assertEquals("After rotating by 720 degrees, player should face the direction North", 1, testAdapter.activePlayerLookingToDirection());

		// rotate by 720 degrees counterclockwise
		i = 0;
		for(int n = 0; n < 8; n++) {
			assertEquals("The first player should face the direction "+directions[i], i+1, testAdapter.activePlayerLookingToDirection());
			testAdapter.rotateActivePlayer(false);
			i--;
			i = (i + 4) % 4;
		}
		
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#performActionForActivePlayer()}.
	 */
	@Test
	public final void testWalkingActionValid() {
		testAdapter.loadLevelFromString(TestLevel.testLevel);

		// walk upside
		testAdapter.performActionForActivePlayer();

		// get the string-representation
		String levelString = testAdapter.levelRepresentationAsString();
		int actionPoints = testAdapter.actionPointsLeft();
		
		// walk upside again - should not be possible because there is a wall,
		// don't change anything
		
		testAdapter.performActionForActivePlayer();
		
		assertEquals("Walking action not possible, don't change level representation.", levelString, testAdapter.levelRepresentationAsString());
		assertEquals("Walking action not possible, don't decrease actionpoints.", actionPoints, testAdapter.actionPointsLeft());
		
		// walk back and turn to enemy
		testAdapter.rotateActivePlayer(true);
		testAdapter.rotateActivePlayer(true);
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(true);
		
		String expectedLevel11 = "" +
			"############\n" +
			"##...#######\n" +
			"##Z.@##...##\n" +
			"##..###Z..##\n" +
			"###.####.###\n" +
			"#.@..##Z..##\n" +
			"#...@....Z##\n" +
			"############";
		String expectedLevel12 = "" +
			"############\n" +
			"##...#######\n" +
			"##Z.@##...##\n" +
			"##..###Z..##\n" +
			"#c#.####=###\n" +
			"#.@..##Z..##\n" +
			"#...@....Z##\n" +
			"############";
		
		// attack alien, but don't change position
		testAdapter.performActionForActivePlayer();
		levelString = testAdapter.levelRepresentationAsString();
		boolean expectedLevelReturned = (expectedLevel11.equals(levelString)) || (expectedLevel12.equals(levelString));
		assertTrue("When attacking an enemy, don't change position of player, " + levelString, expectedLevelReturned);

		String expectedLevel21 = "" +
			"############\n" +
			"##...#######\n" +
			"##Z@.##...##\n" +
			"##..###Z..##\n" +
			"###.####.###\n" +
			"#.@..##Z..##\n" +
			"#...@....Z##\n" +
			"############";
		String expectedLevel22 = "" +
			"############\n" +
			"##...#######\n" +
			"##Z@.##...##\n" +
			"##..###Z..##\n" +
			"#c#.####=###\n" +
			"#.@..##Z..##\n" +
			"#...@....Z##\n" +
			"############";
		
		// walk at the field the alien was placed before
		testAdapter.performActionForActivePlayer();

		levelString = testAdapter.levelRepresentationAsString();
		expectedLevelReturned = (expectedLevel21.equals(levelString)) || (expectedLevel22.equals(levelString));
		assertTrue("After attacking an alien it should be possible to walk at its former gamefield", expectedLevelReturned);
	}
}
